#!/usr/bin/env python3
import ctypes,winsound,mmap

MSP_SUCCESS=0
MSP_TTS_FLAG_DATA_END=2
if __name__ == '__main__':
    ret=MSP_SUCCESS
    login_params=b"appid = 你的科大讯飞的appid, work_dir = ."

    session_begin_params=b"voice_name = xiaona, text_encoding = utf8, sample_rate = 16000, speed = 50, volume = 50, pitch = 50, rdn = 2, background_sound = 1"
    text=(r"Hello,煎饼侠").encode("utf-8")

    wav_header = b'RIFF6n\x06\x00WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00\x80>\x00\x00\x00}\x00\x00\x02\x00\x10\x00data\x00\x00\x00\x00'
    wav_context=mmap.mmap(-1, 1048576, tagname='科大讯飞语音', access=mmap.ACCESS_WRITE)
    
    msc=ctypes.cdll.LoadLibrary('msc_x64.dll')
    ret=msc.MSPLogin(b'',b'',login_params)

    if ret!=MSP_SUCCESS:
        print("MSPLogin failed, error code: %d.\n"% ret)
        exit()

    ret,audio_len, synth_status, getret, wav_datasize = ctypes.c_int(), ctypes.c_int(), ctypes.c_int(), ctypes.c_int(), ctypes.c_int()   
    msc.QTTSSessionBegin.restype=ctypes.c_char_p
    sessionID = msc.QTTSSessionBegin(session_begin_params,ctypes.byref(ret));
    if ret.value!=MSP_SUCCESS:
        print("QTTSSessionBegin failed, error code: %d.\n"% ret.value);
        exit()

    ret = msc.QTTSTextPut(sessionID, text, len(text), None);
    
    wav_context.seek(0)
    wav_context.write(wav_header)
    msc.QTTSAudioGet.restype=ctypes.c_void_p
    while True:
        data=msc.QTTSAudioGet(sessionID, ctypes.byref(audio_len), ctypes.byref(synth_status), ctypes.byref(getret))  
        if audio_len.value>0:
            print('datasize:            %d\r' % wav_datasize.value, end='\r\n')
        if getret.value != MSP_SUCCESS:
            break
        if data:
            wav_context.write(ctypes.string_at(data, audio_len))
            wav_datasize.value += audio_len.value
        if synth_status.value == MSP_TTS_FLAG_DATA_END:  
            break
    WAVE_HEADER_SIZE = 44
    if wav_datasize.value>0:
        wav_size8 = ctypes.c_int()
        wav_size8.value = WAVE_HEADER_SIZE + wav_datasize.value - 8  
        wav_context.seek(4)
        wav_context.write(wav_size8)
        wav_context.seek(40)
        wav_context.write(wav_datasize)
    msc.QTTSSessionEnd(sessionID, "Normal")
    try:
        while True:
            winsound.PlaySound(wav_context, winsound.SND_MEMORY)
    except KeyboardInterrupt:
        wav_context.close()
    
